﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace M3G {
    public class RenderPass : Object3D
    {
        #region Field
        World      world;
        Object3D   target;
        Camera     camera;
        Background background;
        int        viewportX;
        int        viewportY;
        int        viewportWidth;
        int        viewportHeight;
        float      depthRangeNear;
        float      depthRangeFar;
        int        flags;
        #endregion

        #region Method
        public RenderPass () {
            this.world = null;
            this.target = null;
            this.camera = null;
            this.background = null;
            this.viewportX = 0;
            this.viewportY = 0;
            this.viewportWidth = 0;
            this.viewportHeight = 0;
            this.depthRangeNear = 0.0f;
            this.depthRangeFar = 1.0f;
            this.flags = 0;   
        }

        protected RenderPass (RenderPass renderPass) : base(renderPass) {
            this.world = renderPass.world;
            this.target = renderPass.target;
            this.camera = renderPass.camera;
            this.background = renderPass.background;
            this.viewportX = renderPass.viewportX;
            this.viewportY = renderPass.viewportY;
            this.viewportWidth = renderPass.viewportWidth;
            this.viewportHeight = renderPass.viewportHeight;
            this.depthRangeNear = renderPass.depthRangeNear;
            this.depthRangeFar = renderPass.depthRangeFar;
            this.flags = renderPass.flags;
        }

        public World World {
            get { return world; }
        }

        public void SetWorld (World world) {
            this.world = world;
        }
    
        public Background Background {
            get { return background; }
        }

        public void SetBackground (Background background){
            this.background = background;
        }

        public Camera Camera {
            get { return camera; }
        }

        public void SetCamera (Camera camera) {
            this.camera = camera;
        }

        public float DepthRangeFar {
            get { return depthRangeFar; }
        }

        public float DepthRangeNear {
            get { return depthRangeNear; }
        }

        public void SetDepthRange (float near, float far) {
            if (near < 0 || near > 1 || far < 0 || far > 1) {
                throw new ArgumentException ("Near and far must be within [0,1], n=" + near + ",f=" + far);
            }

            this.depthRangeNear = near;
            this.depthRangeFar = far;
        }

    
        public Object3D Target {
            get { return target; }
        }

        public int TargetFlags {
            get { return flags; }
        }


        public void SetTarget (RenderTarget target, int flags) {
            if (flags != 0 && (flags < Graphics3D.Antialias || flags > Graphics3D.Validate)) {
                throw new ArgumentException ("Flags must be one or combination of constants defind in Graphics3D");
            }

            this.target = target;
            this.flags = flags;
            this.viewportX = 0;
            this.viewportY = 0;
            this.viewportWidth = target.Target.Width;
            this.viewportHeight = target.Target.Height;
        }

        public void SetTarget (ImageCube target, int flags) {
            if (flags != 0 && (flags < Graphics3D.Antialias || flags > Graphics3D.Validate)) {
                throw new ArgumentException ("Flags must be one or combination of constants defind in Graphics3D");
            }

            this.target = target;
            this.flags = flags;
            this.viewportX = 0;
            this.viewportY = 0;
            this.viewportWidth = target.Width;
            this.viewportHeight = target.Height;
        }

        public int ViewportHeight {
            get { return viewportHeight; }
        }

        public int ViewportWidth {
            get { return viewportWidth; }
        }

        public int ViewportX {
            get { return viewportX; }
        }

        public int ViewportY {
            get { return viewportY; }
        }

        public void SetViewport (int x, int y, int width, int height) {
            if (width <= 0 || height <= 0) {
                throw new ArgumentException ("Width or Height must be [0,], w=" + width + ",h=" + height);
            }
            // Graphics3DのPropertiesより大きいと例外!

            this.viewportX = x;
            this.viewportY = y;
            this.viewportWidth = width;
            this.viewportHeight = height;
        }

        public override Object3D[] References {
            get {
                var q = new List<Object3D> ();
                q.AddRange (base.References);
                q.Add (world);
                q.Add (target);
                q.Add (camera);
                q.Add (background);
                q.RemoveAll (x => x == null);
                return q.ToArray ();
            }
        }

        public override Object3D Duplicate () {
            return new RenderPass (this);
        }
        #endregion



    }
}
